﻿/*
Wrtiten by Webmaster442 (c) 2009
Uses The ICSharpCode.SharpZLib zip compression module
This is free software. License: GPL V2
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;

namespace loader
{
    public partial class load : Form
    {
        private ZipFile zip;
        private byte[] buffer;
        private List<string> exes;
        private bool hasdata, extractfinished;
        private string extractpath, exe, procname;
        private Thread t;
        private System.Windows.Forms.Timer ti;

        private delegate void UpdateProgressCallback(long fsize, long fpos);
        private delegate void RunCallback();
        private delegate void CloseCallback();

        void Quit()
        {
            this.Visible = false;
            this.Close();
        }

        void ti_Tick(object sender, EventArgs e)
        {
            if (!IsProcessOpen(procname)) Cleanup();
        }

        void Cleanup()
        {
            try
            {
                Directory.Delete(extractpath, true);
            }
            catch (Exception ex) { ;}
            if (ti.Enabled)
            {
                ti.Enabled = false;
                this.Close();
            }
        }

        public bool IsProcessOpen(string name)
        {
            string pname;
            foreach (Process clsProcess in Process.GetProcesses())
            {
                pname = clsProcess.ProcessName.ToUpper();
                if (pname.Contains(name))
                {
                    return true;
                }
            }
            return false;
        }

        private void updateprogress(long fsize, long fpos)
        {
            this.prg_load.Value = Convert.ToInt32((fpos * 100) / fsize);
        }

        private void RunExe()
        {
            this.Visible = false;
            Process filetorun = new Process();
            string[] tempfiles = Directory.GetFiles(extractpath);
            foreach (string file in tempfiles)
            {
                if (file.ToUpper().EndsWith(".EXE"))
                {
                    this.exes.Add(file.ToUpper());
                }
            }
            if (this.exes.Count > 1)
            {
                exeselect exs = new exeselect(this.exes.ToArray());
                if (exs.ShowDialog() == DialogResult.OK) this.exe = this.exes[exs.selectedexe];
            }
            else this.exe = this.exes[0];
            if (string.IsNullOrEmpty(exe))
            {
                MessageBox.Show(Program.localee["no_exe"], Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                Cleanup();
                Close();
            }
            else
            {
                zip.Close();
                zip = null;
                this.buffer = null;
                buffer = null;
                filetorun.StartInfo.FileName = exe;
                filetorun.Start();
                procname = filetorun.ProcessName.ToUpper();
                Thread.Sleep(2000);
                ti.Enabled = true;
            }
        }

        public static string MergePaths(string basePath, string entryName)
        {
            if ((basePath.Length > 0) && (basePath[basePath.Length - 1] != '\\'))
            {
                basePath = basePath + '\\';
            }

            string result = basePath;

            entryName = entryName.Replace('/', '\\');
            result += entryName;

            return result;
        }

        private void extract()
        {
            if (hasdata)
            {
                try
                {
                    this.exes = new List<string>();
                    Random r = new Random();
                    extractpath = Path.GetTempPath() + Convert.ToString(r.Next(5000, 100000), 16);
                    if (!Directory.Exists(extractpath)) Directory.CreateDirectory(extractpath);
                    int read;
                    for (int index = 0; index < zip.Count; ++index)
                    {
                        if (zip[index].IsFile)
                        {
                            Stream input = zip.GetInputStream(index);
                            using (FileStream output = File.OpenWrite(MergePaths(extractpath, zip[index].Name)))
                            {
                                do
                                {
                                    read = input.Read(this.buffer, 0, this.buffer.Length);
                                    output.Write(buffer, 0, read);
                                }
                                while (read > 0);
                            }
                        }
                        this.Invoke(new UpdateProgressCallback(this.updateprogress), new object[] { zip.Count, index });
                    }
                    this.extractfinished = true;
                    this.Invoke(new RunCallback(this.RunExe));
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.Invoke(new CloseCallback(Quit));
                }
            }
        }

        public load()
        {
            InitializeComponent();
            if (Program.localee.issupported) this.label1.Text = Program.localee["extracting"];
            try
            {
                zip = new ZipFile(Application.ExecutablePath);
                if (zip.Count > 0)
                {
                    setpass pwd = new setpass();
                    ti = new System.Windows.Forms.Timer();
                    ti.Enabled = false;
                    ti.Interval = 1000;
                    ti.Tick += new EventHandler(ti_Tick);
                    hasdata = true;
                    if (zip[0].IsCrypted)
                    {
                        if (pwd.ShowDialog() == DialogResult.OK) zip.Password = pwd.passwd;
                        else
                        {
                            Program.needtoquit = true;
                            return;
                        }
                    }
                    buffer = new byte[16384];
                    t = new Thread(extract);
                    t.Start();
                }
                else
                {
                    MessageBox.Show(Program.localee["no_compressed_data"], Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Program.needtoquit = true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                Program.needtoquit = true;
            }
        }

        private void load_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!extractfinished)
            {
                if (t != null && t.IsAlive) t.Abort();
                this.Visible = false;
                Thread.Sleep(1000);
                this.Cleanup();
            }
        }
    }
}
